Aims and Hypotheses

Hypothesis 1: Discordance is a relatively common, yet under appreciated phenomenon, and varies by geographic location of care and patient attributes including demographics, severity of illness, and underlying disease process.

Hypothesis 2: Discordance between aPTT and anti-Xa indicates the presence of coagulation system pathophysiology which is a risk factor for development of hemorrhage and thrombosis.

Classic systemic anticoagulation goals, anti-Xa vs aPTT, at NYP:

Typical anti-Xa goal vs aPTT goals among heparinized ECMO patients:

Source: NYP GUIDLINE “UNFRACTIONATED HEPARIN INTRAVENOUS (IV) DOSING AND MONITORING FOR ADULT INPATIENTS RECEIVING EXTRACORPOREAL MEMBRANE OXYGENATION (ECMO)” Approved Dec 2022

Methods:

Only first ECMO run used.

ECMO duration: Dr. Connie Nguyen manually reviewed heparin-exposed patients’ EMRs in June 2025 to identify true ECMO time off, as initial data review identified some labs that were drawn while on heparin but after the patient was off ECMO. The variable “time_off” in the original data was obtained from ELSO sources. Per Dr. Nguyen’s review, if her evaluation of ECMO stop time was within 4 hours of ELSO-derived time_off, then the actual true time off was deemed as that known by ELSO. If there was a greater than 4 hour discrepancy, a new time_off_true value was recorded.

Lab cutoffs:

Hyperbilirubinemia can artifactually elevate anti-Xa (colorimetric assay). Jaundice threshold is 2 - 3 mg/dL total bilirubin. Upper limit of normal total bilirubin at NYP-CUIMC is 1.2 mg/dL.

Bilirubin is measured in separate tubes compared to aPTT, anti-Xa, INR, and fibrinogen. As hyperbilirubinemia can impact assessment of anti-Xa but also may not change rapidly from one moment to another, we accounted for total bilirubin by computing the nearest_bilirubin value within 24 hours of any aPTT. (aPTT chosen as it was the most frequently measured coagulation lab).

Likewise, platelet count is measured in separate tubes compared to aPTT, anti-Xa, INR, and fibrinogen. Thrombocytopenia can impact discordance (PMID 38725133). Thus, we computed nearest_platelet value within 24 hours of any aPTT, in a manner comparable to that of nearest_bilirubin.

COMPLICATIONS: all complications reviewed were documented during ECMO duration, with exception of clinically significant bleeding and thrombotic complications which were manually assessed by Connie and Phil as follows:

Basic Lab Counts and Scatterplot visualization among ECMO paients who received heparin exposed

count of distinct MRNs of patients exposed to heparin TOTAL
n
165
counts of MRNs of patients exposed to heparin by location TOTAL - these do not all have anti-Xa and aPTT matched pairs FYI; counts between distinct MRNs and department_name may not match as some patients move between departments
department_name n
MIL 5 CTICU 76
MIL 5 CCU 41
MIL 4 MICU A 31
HRT CARDIAC CARE 25
MIL OPERATING ROOM 5
MIL 4 SICU 1
MIL CARDIAC CATH 1
GBG 4 W CT ICU 1

count of distinct MRNs of patients exposed to heparin who have TIME-MATCHED anti-Xa and aPTT pairs
n
113
counts of distinct MRNs by location of patients exposed to heparin who have TIME-MATCHED anti-Xa and aPTT pairs; counts between distinct MRNs and department_name may not match as some patients move between departments
department_name n
MIL 5 CTICU 56
MIL 5 CCU 31
HRT CARDIAC CARE 22
MIL 4 MICU A 6
MIL 4 SICU 1
MIL OPERATING ROOM 1
MIL CARDIAC CATH 1
GBG 4 W CT ICU 1

## # A tibble: 1 × 1
##   correlation
##         <dbl>
## 1       0.740

Polynomial Fitting

This fits a second degree polynomial on aPTT and accounts for repeated measures per patient (i.e. multiple labs per individual patient) by including a random intercept for each patient. This is important as the repeated measures per patient are not independent - the labs are dependent on the baseline values (and the baseline anti-Xa between patients who have the same aPTT may not be the same, or vice versa).

95% prediction interval chosen to balance sensitivity and specificity.

list of MRNs with aPTT > antiXa
x
1001491594
1002467250
1006905710
1007129753
1009477257
1010147999
1011043983
1011077110
1100547209
1102078503
1201199342
1400032239
1400969240
1401183967
1401327774
1401468984
1401639110
1401766288
list of MRNs with aPTT < antiXa
x
1001491594
1003642179
1009544965
1010696012
1101397979
1102216636
1201555171
1401554006
1401591974
1401611898
1401682296
1401683148
1401689750
1401696145
1401697961
1401707171
1401796928
1401848048
1401991907
## Adding missing grouping variables: `mrn`, `lab_result_time`
aPTT > antiXa, time-matched pairs
mrn lab_result_time activated_partial_thromboplastin_time heparin_assay_quantitative
1001491594 2024-08-24 22:45:00 96.9 0.36
1002467250 2024-12-12 18:30:00 63.5 0.26
1006905710 2024-10-10 18:02:00 71.3 0.07
1006905710 2024-10-11 06:23:00 56.2 0.16
1007129753 2024-04-12 06:13:00 43.5 0.10
1007129753 2024-04-12 18:41:00 42.9 0.10
1007129753 2024-04-13 06:08:00 43.8 0.10
1007129753 2024-04-13 18:00:00 45.2 0.10
1009477257 2024-12-02 15:04:00 41.9 0.09
1010147999 2024-02-20 18:35:00 60.3 0.10
1010147999 2024-02-21 12:35:00 52.6 0.10
1011043983 2024-06-17 17:05:00 75.4 0.33
1011043983 2024-06-17 22:39:00 93.2 0.37
1011043983 2024-06-18 04:34:00 93.8 0.36
1011043983 2024-06-18 09:40:00 106.5 0.40
1011043983 2024-06-18 16:00:00 103.4 0.43
1011043983 2024-06-18 22:46:00 89.5 0.37
1011043983 2024-06-19 05:51:00 106.0 0.43
1011043983 2024-06-19 11:46:00 122.7 0.46
1011043983 2024-06-20 11:59:00 104.6 0.48
1011077110 2024-05-20 06:06:00 58.1 0.14
1011077110 2024-05-21 06:42:00 70.1 0.23
1100547209 2024-05-02 14:06:00 119.4 0.60
1102078503 2025-01-07 10:13:00 36.9 0.04
1201199342 2024-09-26 12:28:00 76.7 0.34
1400032239 2024-03-18 23:46:00 45.6 0.10
1400969240 2024-10-13 23:20:00 39.7 0.05
1400969240 2024-10-14 18:13:00 38.5 0.06
1401183967 2024-03-30 18:34:00 102.0 0.30
1401327774 2024-11-03 03:56:00 122.1 0.38
1401327774 2024-11-03 11:13:00 94.3 0.38
1401327774 2024-11-03 19:02:00 63.2 0.22
1401468984 2024-02-24 07:04:00 42.8 0.10
1401468984 2024-02-27 18:47:00 55.3 0.20
1401639110 2024-08-20 06:59:00 64.4 0.16
1401766288 2024-07-31 06:09:00 60.3 0.21
## # A tibble: 1 × 2
##   mean_aptt mean_antiXa
##       <dbl>       <dbl>
## 1      72.3       0.241
aPTT > antiXa, time-matched pairs, counts of typical concordance if classic anticoagulation goals at CUIMC used
concordance_classic_simple n
concordant 13
discordant aPTT above antiXa 22
high aPTT low antiXa 1
## Adding missing grouping variables: `mrn`, `lab_result_time`
aPTT > antiXa, time-matched pairs, counts of typical concordance if low anticoagulation goals at CUIMC used
concordance_low_simple n
concordant 20
discordant aPTT above antiXa 15
high aPTT low antiXa 1
aPTT < antiXa, time-matched pairs
mrn lab_result_time activated_partial_thromboplastin_time heparin_assay_quantitative
1001491594 2024-08-20 04:09:00 41.8 0.47
1001491594 2024-08-20 10:16:00 55.3 0.59
1001491594 2024-08-20 21:41:00 61.2 0.67
1001491594 2024-08-21 05:17:00 66.8 0.74
1001491594 2024-08-22 09:33:00 46.4 0.43
1003642179 2024-01-12 05:15:00 63.9 0.56
1009544965 2024-01-31 14:58:00 98.6 0.90
1009544965 2024-02-01 01:05:00 92.9 0.80
1009544965 2024-02-01 17:11:00 68.1 0.60
1009544965 2024-02-02 00:55:00 57.2 0.50
1010696012 2024-04-01 03:44:00 44.3 0.40
1010696012 2024-04-01 09:37:00 46.2 0.40
1010696012 2024-04-03 06:25:00 35.1 0.30
1101397979 2024-02-23 22:03:00 170.7 1.70
1101397979 2024-02-28 12:44:00 55.8 0.50
1102216636 2024-08-29 04:04:00 67.8 0.62
1201555171 2024-10-05 01:13:00 44.3 0.40
1201555171 2024-10-05 12:40:00 56.2 0.63
1201555171 2024-10-05 19:00:00 53.4 0.57
1201555171 2024-10-06 01:07:00 44.7 0.45
1201555171 2024-10-06 06:29:00 38.2 0.34
1401554006 2024-01-15 03:42:00 39.2 0.33
1401554006 2024-01-15 18:16:00 41.4 0.39
1401554006 2024-01-16 05:37:00 43.8 0.39
1401591974 2024-02-08 03:45:00 70.3 0.70
1401591974 2024-02-10 17:55:00 44.5 0.40
1401591974 2024-02-12 05:09:00 53.4 0.50
1401611898 2024-04-10 12:45:00 48.0 0.40
1401611898 2024-04-11 07:22:00 35.4 0.30
1401611898 2024-04-11 20:24:00 46.9 0.40
1401611898 2024-04-12 05:14:00 41.9 0.40
1401611898 2024-04-12 12:44:00 43.7 0.40
1401682296 2024-04-17 04:01:00 36.3 0.30
1401683148 2024-05-24 05:06:00 51.2 0.40
1401689750 2024-04-22 05:22:00 60.2 0.60
1401689750 2024-04-23 05:38:00 45.7 0.50
1401689750 2024-04-24 04:17:00 39.8 0.40
1401689750 2024-04-25 04:24:00 39.4 0.40
1401696145 2024-05-07 19:31:00 47.0 0.40
1401697961 2024-04-29 19:21:00 33.8 0.30
1401707171 2024-05-10 19:23:00 39.4 0.50
1401707171 2024-05-11 04:21:00 34.0 0.30
1401707171 2024-05-11 11:42:00 30.7 0.30
1401707171 2024-05-12 07:19:00 34.4 0.40
1401707171 2024-05-12 12:43:00 34.9 0.30
1401707171 2024-05-12 22:13:00 35.1 0.40
1401707171 2024-05-13 03:56:00 35.5 0.40
1401707171 2024-05-13 21:40:00 28.6 0.30
1401796928 2024-07-25 18:01:00 43.9 0.51
1401848048 2024-09-10 01:40:00 48.4 0.43
1401848048 2024-09-10 06:43:00 53.5 0.50
1401848048 2024-09-10 12:27:00 53.2 0.54
1401991907 2024-12-09 06:48:00 39.2 0.34
1401991907 2024-12-09 19:11:00 40.2 0.36
1401991907 2024-12-10 00:53:00 40.0 0.37
1401991907 2024-12-10 06:26:00 36.4 0.35
1401991907 2024-12-10 13:57:00 39.8 0.34
1401991907 2024-12-10 18:34:00 38.6 0.38
## # A tibble: 1 × 2
##   mean_aptt mean_antiXa
##       <dbl>       <dbl>
## 1      49.6       0.474
## Adding missing grouping variables: `mrn`, `lab_result_time`
aPTT < antiXa, time-matched pairs, counts of typical concordance if classic anticoagulation goals at CUIMC used
concordance_classic_simple n
concordant 19
discordant aPTT below antiXa 38
low aPTT high antiXa 1
aPTT < antiXa, time-matched pairs, counts of typical concordance if classic anticoagulation goals at CUIMC used
concordance_low_simple n
concordant 22
discordant aPTT below antiXa 35
low aPTT high antiXa 1
MRN of patients with both discordance types; n = # of discordance types
mrn n
1001491594 2
## # A tibble: 7 × 3
## # Groups:   lab_result_time, unusual_type [7]
##   lab_result_time     unusual_type      n
##   <dttm>              <fct>         <int>
## 1 2024-08-20 04:09:00 aPTT < antiXa     1
## 2 2024-08-20 10:16:00 aPTT < antiXa     1
## 3 2024-08-20 21:41:00 aPTT < antiXa     1
## 4 2024-08-21 05:17:00 aPTT < antiXa     1
## 5 2024-08-22 09:33:00 aPTT < antiXa     1
## 6 2024-08-23 05:28:00 concordant        1
## 7 2024-08-24 22:45:00 aPTT > antiXa     1

Study ID 5 (MRN 1001491594) had both discordance types (aPTT > antiXa and aPTT < antiXa).

Perhaps it would be worth retaining this patient in the model, as discordance could contribute to hemorrhage and/or thrombosis in separate instances.

count of unusual type lab pairs
unusual_type n
concordant 477
aPTT > antiXa 36
aPTT < antiXa 58
## # A tibble: 6 × 4
##   conc  high  low       n
##   <lgl> <lgl> <lgl> <int>
## 1 FALSE FALSE TRUE      5
## 2 FALSE TRUE  FALSE     3
## 3 TRUE  FALSE FALSE    77
## 4 TRUE  FALSE TRUE     13
## 5 TRUE  TRUE  FALSE    14
## 6 TRUE  TRUE  TRUE      1
## # A tibble: 3 × 2
##   first_discord_type     n
##   <chr>              <int>
## 1 aPTT < antiXa         19
## 2 aPTT > antiXa         17
## 3 concordant            77

Interpreting:

77 patients: always concordant

17 patients: ever high only (aPTT > antiXa)

19 patients: ever low only (aPTT < antiXa)

1 patient: both high AND low

Patient-Level Demographics, based on development of any discordance

Note that one patient with both discordance groups is included in this analysis. This patient’s first discordance type was “aPTT < antiXa”

Kruskal-Wallis rank sum test results, subject w both discordance types excluded
discord_group n_patients median_age iqr_age male_pct median_wt iqr_wt median_ht iqr_ht median_hours iqr_hours cticu_pct ccu_pct micu_pct otherloc_pct vv_pct va_pct female_pct median_aptt iqr_appt median_antixa iqr_antixa median_inr iqr_inr median_fibrinogen iqr_fibrinogen median_bilirubin iqr_bilirubin median_platelets iqr_platelets median_hep_dose iqr_hep_dose
aPTT < antiXa 18 60 19 55.56 99.05 22.5 171.6 13.30 164.5 114.75 16.67 83.33 0.00 0.00 5.56 83.33 44.44 42.90 11.44 0.36 0.14 1.2 0.14 349.0 274.62 0.7 1.55 123.75 58.5 9.5 6
aPTT > antiXa 17 58 16 52.94 73.00 20.4 167.6 13.00 192.0 259.00 64.71 29.41 0.00 5.88 5.88 76.47 47.06 50.55 12.90 0.17 0.13 1.2 0.17 466.5 267.00 2.0 1.10 85.50 65.0 9.0 6
never discordant 77 56 21 67.53 84.80 29.7 170.2 12.93 114.0 108.00 53.25 36.36 7.79 2.60 16.88 63.64 32.47 34.00 10.15 0.15 0.12 1.1 0.20 477.5 322.00 0.8 0.95 103.00 61.5 6.0 6
Pairwise Wilcoxon Rank Sum test results, without correction for multiple testing
variable p_value
age_years 0.8123
weight 0.0013
height 0.3491
hours_ecmo 0.0420
activated_partial_thromboplastin_time 0.0000
heparin_assay_quantitative 0.0000
international_normalization_ratio 0.0823
fibrinogen 0.2517
nearest_bilirubin 0.0121
nearest_platelet 0.0453
heparin_infusion_dose_value_units_kg_hr 0.0192
Vertical Summary Table with Discordance Groups Across Columns and KW P-values
variable group1 group2 p.value
age_years aPTT > antiXa aPTT < antiXa 0.8171
age_years never discordant aPTT < antiXa 0.7359
age_years never discordant aPTT > antiXa 0.5554
weight aPTT > antiXa aPTT < antiXa 0.0003
weight never discordant aPTT < antiXa 0.0169
weight never discordant aPTT > antiXa 0.0248
height aPTT > antiXa aPTT < antiXa 0.2033
height never discordant aPTT < antiXa 0.6203
height never discordant aPTT > antiXa 0.2046
hours_ecmo aPTT > antiXa aPTT < antiXa 0.5747
hours_ecmo never discordant aPTT < antiXa 0.1699
hours_ecmo never discordant aPTT > antiXa 0.0191
activated_partial_thromboplastin_time aPTT > antiXa aPTT < antiXa 0.1949
activated_partial_thromboplastin_time never discordant aPTT < antiXa 0.0008
activated_partial_thromboplastin_time never discordant aPTT > antiXa 0.0000
heparin_assay_quantitative aPTT > antiXa aPTT < antiXa 0.0000
heparin_assay_quantitative never discordant aPTT < antiXa 0.0000
heparin_assay_quantitative never discordant aPTT > antiXa 0.3838
international_normalization_ratio aPTT > antiXa aPTT < antiXa 0.5597
international_normalization_ratio never discordant aPTT < antiXa 0.1807
international_normalization_ratio never discordant aPTT > antiXa 0.0472
fibrinogen aPTT > antiXa aPTT < antiXa 0.2544
fibrinogen never discordant aPTT < antiXa 0.1218
fibrinogen never discordant aPTT > antiXa 0.8572
nearest_bilirubin aPTT > antiXa aPTT < antiXa 0.0643
nearest_bilirubin never discordant aPTT < antiXa 0.6826
nearest_bilirubin never discordant aPTT > antiXa 0.0027
nearest_platelet aPTT > antiXa aPTT < antiXa 0.0167
nearest_platelet never discordant aPTT < antiXa 0.2151
nearest_platelet never discordant aPTT > antiXa 0.0589
heparin_infusion_dose_value_units_kg_hr aPTT > antiXa aPTT < antiXa 0.3721
heparin_infusion_dose_value_units_kg_hr never discordant aPTT < antiXa 0.0071
heparin_infusion_dose_value_units_kg_hr never discordant aPTT > antiXa 0.1874
Categorical Variable Tests (Chi-square or Fisher Automatically Selected)
variable aPTT < antiXa aPTT > antiXa never discordant p_value
activated_partial_thromboplastin_time 42.9 (IQR 11.4) 50.5 (IQR 12.9) 34.0 (IQR 10.2) 0.0000
age_years 60.0 (IQR 19.0) 58.0 (IQR 16.0) 56.0 (IQR 21.0) 0.8123
fibrinogen 349.0 (IQR 274.6) 466.5 (IQR 267.0) 477.5 (IQR 322.0) 0.2517
height 171.6 (IQR 13.3) 167.6 (IQR 13.0) 170.2 (IQR 12.9) 0.3491
heparin_assay_quantitative 0.4 (IQR 0.1) 0.2 (IQR 0.1) 0.2 (IQR 0.1) 0.0000
heparin_infusion_dose_value_units_kg_hr 9.5 (IQR 6.0) 9.0 (IQR 6.0) 6.0 (IQR 6.0) 0.0192
hours_ecmo 164.5 (IQR 114.8) 192.0 (IQR 259.0) 114.0 (IQR 108.0) 0.0420
international_normalization_ratio 1.2 (IQR 0.1) 1.2 (IQR 0.2) 1.1 (IQR 0.2) 0.0823
nearest_bilirubin 0.7 (IQR 1.6) 2.0 (IQR 1.1) 0.8 (IQR 0.9) 0.0121
nearest_platelet 123.8 (IQR 58.5) 85.5 (IQR 65.0) 103.0 (IQR 61.5) 0.0453
weight 99.0 (IQR 22.5) 73.0 (IQR 20.4) 84.8 (IQR 29.7) 0.0013
Counts and Percentages of Categorical Variables by Discordance Group
variable p_value
sex 0.3975
department_name 0.0263
mode 0.7435
support_type 0.0118
covid19 0.1969
variable aPTT < antiXa aPTT > antiXa never discordant
Female 8 (44.4%) 8 (47.1%) 25 (32.5%)
Male 10 (55.6%) 9 (52.9%) 52 (67.5%)
MIL 5 CCU 10 (55.6%) 2 (11.8%) 16 (20.8%)
MIL 5 CTICU 3 (16.7%) 11 (64.7%) 40 (51.9%)
MIL 4 SICU NA NA 1 (1.3%)
MIL OPERATING ROOM NA NA 1 (1.3%)
HRT CARDIAC CARE 5 (27.8%) 3 (17.6%) 12 (15.6%)
MIL 4 MICU A NA NA 6 (7.8%)
MIL CARDIAC CATH NA 1 (5.9%) NA
GBG 4 W CT ICU NA NA 1 (1.3%)
Conversion 2 (11.1%) 3 (17.6%) 13 (16.9%)
VA 15 (83.3%) 13 (76.5%) 49 (63.6%)
VV 1 (5.6%) 1 (5.9%) 13 (16.9%)
VVA NA NA 2 (2.6%)
Cardiac 17 (94.4%) 14 (82.4%) 48 (62.3%)
ECPR NA 2 (11.8%) 4 (5.2%)
Pulmonary 1 (5.6%) 1 (5.9%) 25 (32.5%)
4 7 (38.9%) 5 (29.4%) 12 (15.6%)
NA 11 (61.1%) 12 (70.6%) 65 (84.4%)

Patient-level Demographics, based on FIRST DISCORDANCE TYPE ONLY - descriptive only for consideration in survival analyses (which are based on first discordance type), not planning to report

Note that the one patient with both discordance groups is included in this analysis had a FIRST discordance type was “aPTT < antiXa”. This patient is dropped for between-group comparison.

name concordant aPTT > antiXa aPTT < antiXa
n_patients 96.00 7.00 10.00
n_labs 473.00 45.00 53.00
median_age 56.00 58.00 51.00
iqr_age 23.00 7.00 28.00
male_pct 63.42 91.11 56.60
median_wt 86.00 83.90 98.50
iqr_wt 30.70 13.00 9.10
median_ht 170.20 167.60 175.00
iqr_ht 15.20 7.70 17.80
median_hours 203.00 106.00 189.00
iqr_hours 241.00 248.00 100.00
cticu_pct 39.96 28.89 24.53
ccu_pct 38.05 2.22 39.62
hrtccu_pct 18.82 66.67 35.85
micu_pct 2.11 0.00 0.00
vv_pct 10.15 0.00 1.89
va_pct 67.65 100.00 96.23
vva_pct 2.54 0.00 0.00
convert_pct 19.66 0.00 1.89
median_flow4 3.10 3.20 2.80
iqr_flow4 0.80 0.20 1.00
median_flow24 3.30 3.00 3.40
iqr_flow24 0.70 0.20 0.60
median_aptt 37.40 58.10 41.80
iqr_aptt 14.20 43.10 21.30
median_antixa 0.18 0.30 0.38
iqr_antixa 0.19 0.18 0.26
median_inr 1.10 1.20 1.20
iqr_inr 0.20 0.10 0.20
median_fibrinogen 482.00 592.50 300.50
iqr_fibrinogen 349.00 246.50 153.75
median_heparin_dose 9.00 12.00 8.00
iqr_heparin_dose 6.50 6.00 4.00
median_nearest_bilirubin 1.10 1.70 0.70
iqr_nearest_bilirubin 1.20 1.60 0.40

Discordance vs Geographic ICU and Support Type

##        
##         concordant aPTT > antiXa aPTT < antiXa
##   ccu          271            16            53
##   cticu        191            19             5
##   micu          10             0             0
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_locations
## p-value = 1.245e-06
## alternative hypothesis: two.sided
##            
##             concordant aPTT > antiXa aPTT < antiXa
##   Cardiac          365            31            57
##   ECPR              32             3             0
##   Pulmonary         80             2             1
##                mode
## unusual_type     VA  VV
##   concordant    338  46
##   aPTT > antiXa  30   2
##   aPTT < antiXa  48   1
## 
##  Fisher's Exact Test for Count Data
## 
## data:  .
## p-value = 0.05746
## alternative hypothesis: two.sided

Safety checks to ensure only including labs and complication that were measured between ECMO start and 7 days following ECMO STOP

# safety check to ensure only including labs that were measured after ecmo start or before 7 days following ECMO stop
model_fit_data %>%
  filter(lab_result_time < time_on | lab_result_time > complication_7day_assessment)
## # A tibble: 0 × 141
## # ℹ 141 variables: study_id <int>, mrn <chr>, patient_name <chr>,
## #   time_on <dttm>, time_off <dttm>, time_off_true <dttm>,
## #   complication_7day_assessment <dttm>, duration_to_lab <dbl>,
## #   patient_id <chr>, run_id <chr>, lab_result_time <dttm>,
## #   department_name <fct>, heparin_infusion_dose_value_units_kg_hr <dbl>,
## #   concordance_classic <fct>, concordance_low <fct>,
## #   concordance_classic_simple <fct>, concordance_low_simple <fct>, …
## check shows no data -> all is okay
#safety check to ensure only including complications that were measured after ecmo start or before 7 days following ECMO stop
model_fit_data %>%
  pivot_longer(
    death_date:ich_based_on_imaging_findings,
    names_to = "complication",
    values_to = "time_complication") %>% 
  filter(time_complication < time_on | time_complication > complication_7day_assessment)
## # A tibble: 0 × 100
## # ℹ 100 variables: study_id <int>, mrn <chr>, patient_name <chr>,
## #   time_on <dttm>, time_off <dttm>, time_off_true <dttm>,
## #   complication_7day_assessment <dttm>, duration_to_lab <dbl>,
## #   patient_id <chr>, run_id <chr>, lab_result_time <dttm>,
## #   department_name <fct>, heparin_infusion_dose_value_units_kg_hr <dbl>,
## #   concordance_classic <fct>, concordance_low <fct>,
## #   concordance_classic_simple <fct>, concordance_low_simple <fct>, …
## check shows no data -> all is okay

COMPLICATION ANALYSES

Complications are assessed only if they occur after a lab (discordance) result time and before 7 days after ECMO stop.

Created composite hemorrhagic and thrombotic outcomes, grouped as below.

Complication Composite Groupings

Any Hemorrhagic Complication = hemorrhage_any

  • neurologic_intra_extra_parenchymal_cns_hemorrhage_us_or_ct_or_mri

  • hemorrhagic_gi_hemorrhage

  • major_bleeding_perfusion

  • hemorrhagic_peripheral_cannulation_site_bleeding

  • pulmonary_pulmonary_hemorrhage

  • hemorrhagic_surgical_site_bleeding

  • hemorrhagic_mediastinal_cannulation_site_bleeding

  • gi_bleeding_present_on_cta_and_confirmed_via_endoscopy***

  • ich_based_on_imaging_findings***

Any Thrombotic Complication = thrombosis_any

  • neurologic_cns_infarction_us_or_ct_or_mri

  • limb_ischemia

  • mechanical_thrombosis_clots_circuit_component

  • circuit_thrombosis_perfusion

  • dvt_pe_1_time_and_date***

  • ischemic_stroke_1_time_and_date***

  • acute_limb_ischemia_1_time_and_date***

not included in thrombosis composite as unlikely to be biologically related to discordance:

  • neurologic_cns_diffuse_ischemia_ct_mri

  • limb_fasciotomy

*** = complications as reviewed manually by Phil/Connie

Skipped as could violate causal time pathway between discordance -> complication

  • dvt_pe_2_time_and_date

  • dvt_pe_3_time_and_date

  • dvt_pe_4_time_and_date

  • acute_limb_ischemia_2_time_and_date

  • acute_limb_ischemia_3_time_and_date

  • ischemic_stroke_2_time_and_date

  • ischemic_stroke_3_time_and_date

Complication Subtype Counts by Discordance Group (Rows = Complications)
complication aPTT < antiXa aPTT > antiXa never discordant
any_acute_limb_ischemia_1_time_and_date 0 2 7
any_circuit_thrombosis_perfusion 3 1 15
any_dvt_pe_1_time_and_date 1 2 14
any_gi_bleeding_present_on_cta_and_confirmed_via_endoscopy 0 1 0
any_hemorrhagic_gi_hemorrhage 0 0 1
any_hemorrhagic_mediastinal_cannulation_site_bleeding 0 0 0
any_hemorrhagic_peripheral_cannulation_site_bleeding 0 1 0
any_hemorrhagic_surgical_site_bleeding 0 0 1
any_ich_based_on_imaging_findings 1 2 0
any_ischemic_stroke_1_time_and_date 0 2 2
any_limb_ischemia 0 0 0
any_major_bleeding_perfusion 0 1 1
any_mechanical_thrombosis_clots_circuit_component 0 0 0
any_neurologic_cns_infarction_us_or_ct_or_mri 0 1 0
any_neurologic_intra_extra_parenchymal_cns_hemorrhage_us_or_ct_or_mri 0 0 0
any_pulmonary_pulmonary_hemorrhage 0 0 0
hemorrhage_any 1 4 3
thrombosis_any 4 6 34
patient_model_data <- patient_level_complications %>%
  left_join(patient_demographics, by = "mrn") %>% 
  filter(discord_group != "both types") %>% 
  mutate(
    discord_group = fct_relevel(discord_group, "never discordant"),
    icu_type = case_when(
      department_name == "MIL 5 CCU" ~ "ccu",
      department_name == "MIL 5 CTICU" ~ "cticu",
      department_name == "MIL 4 SICU" ~ "other",
      department_name == "MIL OPERATING ROOM" ~ "other",
      department_name == "HRT CARDIAC CARE" ~ "ccu",
      department_name == "MIL 4 MICU A" ~ "micu",
      department_name == "MIL CARDIAC CATH" ~ "other",
      department_name == "PBY ADULT EMERGENCY" ~ "other",
      department_name == "MIL 4 MICU B" ~ "micu",
      department_name == "GBG 4 W CT ICU" ~ "other",
      department_name == "MIL 9 HUDSON" ~ "other",
      department_name == "POST-DISCHARGE" ~ "other",
      TRUE ~ NA)) %>% 
  filter(icu_type != "other")

1. patient-level analyses

Fibrinogen only measured in 38 patients, thus cannot be included as a covariable

Note that this does not preserve time-matching of labs, which is problematic, and is based

hemorrhage_patient_glm <- glm(
  hemorrhage_any ~ discord_group,
  data = patient_model_data,
  family = binomial)

hemorrhage_patient_glm %>% broom::tidy(exponentiate = TRUE, conf.int = TRUE) %>% kable(digits = 3, caption = "Univariable regression with composite hemorrhage outcome")
Univariable regression with composite hemorrhage outcome
term estimate std.error statistic p.value conf.low conf.high
(Intercept) 0.042 0.589 -5.368 0.000 0.010 0.113
discord_groupaPTT < antiXa 1.392 1.186 0.279 0.780 0.067 11.659
discord_groupaPTT > antiXa 7.889 0.825 2.503 0.012 1.560 44.499
hemorrhage_multivariable_patient_glm <-glm(
  hemorrhage_any ~ discord_group + international_normalization_ratio + nearest_bilirubin + heparin_infusion_dose_value_units_kg_hr + weight + nearest_platelet,
  data = patient_model_data,
  family = binomial)

hemorrhage_multivariable_patient_glm %>% broom::tidy(exponentiate = TRUE, conf.int = TRUE) %>% kable(digits = 3, caption = "Multivariable regression with composite outcome")
Multivariable regression with composite outcome
term estimate std.error statistic p.value conf.low conf.high
(Intercept) 0.005 2.830 -1.904 0.057 0.000 0.773
discord_groupaPTT < antiXa 1.356 1.455 0.209 0.834 0.043 19.661
discord_groupaPTT > antiXa 3.987 0.978 1.415 0.157 0.575 29.478
international_normalization_ratio 70.410 2.295 1.853 0.064 1.010 9931.450
nearest_bilirubin 0.780 0.423 -0.588 0.556 0.288 1.557
heparin_infusion_dose_value_units_kg_hr 1.089 0.116 0.736 0.462 0.866 1.380
weight 0.971 0.025 -1.196 0.232 0.919 1.014
nearest_platelet 0.994 0.012 -0.476 0.634 0.969 1.017
thrombosis_patient_glm <- glm(
  thrombosis_any ~ discord_group,
  data = patient_model_data,
  family = binomial)

thrombosis_patient_glm %>% broom::tidy(exponentiate = TRUE, conf.int = TRUE) %>% kable(digits = 3, caption = "Univariable regression with thrombosis composite outcome")
Univariable regression with thrombosis composite outcome
term estimate std.error statistic p.value conf.low conf.high
(Intercept) 0.805 0.234 -0.928 0.353 0.506 1.271
discord_groupaPTT < antiXa 0.355 0.613 -1.689 0.091 0.094 1.098
discord_groupaPTT > antiXa 0.745 0.567 -0.518 0.604 0.233 2.223
thrombosis_multivariable_patient_glm <-glm(
  thrombosis_any ~ discord_group + international_normalization_ratio + nearest_bilirubin + heparin_infusion_dose_value_units_kg_hr + nearest_platelet + weight,
  data = patient_model_data,
  family = binomial)

thrombosis_multivariable_patient_glm %>% broom::tidy(exponentiate = TRUE, conf.int = TRUE) %>% kable(digits = 3, caption = "Multivariable regression with thrombosis composite outcome")
Multivariable regression with thrombosis composite outcome
term estimate std.error statistic p.value conf.low conf.high
(Intercept) 0.611 1.619 -0.304 0.761 0.026 16.483
discord_groupaPTT < antiXa 0.531 0.676 -0.937 0.349 0.126 1.894
discord_groupaPTT > antiXa 0.723 0.652 -0.497 0.619 0.188 2.539
international_normalization_ratio 2.541 1.328 0.702 0.483 0.177 35.738
nearest_bilirubin 0.841 0.187 -0.928 0.353 0.560 1.190
heparin_infusion_dose_value_units_kg_hr 0.954 0.060 -0.785 0.433 0.845 1.072
nearest_platelet 1.001 0.005 0.120 0.905 0.990 1.011
weight 0.996 0.009 -0.428 0.669 0.978 1.013

2. Survival Analyses

Patients by first discordance type (static classification)
first_discord_type n
concordant 77
aPTT > antiXa 17
aPTT < antiXa 19

2.2 Sanity checks: event timing vs discordance timing

Patients with thrombosis BEFORE first discordance time
mrn time_on first_discord_time first_discord_type clot_first censor_time
1201199342 2024-09-09 17:56:00 2024-09-26 12:28:00 aPTT > antiXa 2024-09-23 22:16:00 2024-10-12 17:50:00
Patients with hemorrhage BEFORE first discordance time
mrn time_on first_discord_time first_discord_type bleed_first censor_time
Patients whose first discordance occurs AFTER the 7-day window
mrn time_on censor_time first_discord_time first_discord_type

2.3 Static KM curves (discordance as fixed at first discordance)

Static: any thrombosis during follow-up?
event_throm n
0 69
1 44
Static: any hemorrhage during follow-up?
event_bleed n
0 106
1 7
## Ignoring unknown labels:
## • colour : "First discordance type"

## Ignoring unknown labels:
## • colour : "First discordance type"

2.4 Time-varying exposure: everyone starts concordant, then switches at first discordance

Time-varying thrombosis data: group membership at time 0
discord_group n
concordant 113
Time-varying bleeding data: group membership at time 0
discord_group n
concordant 113

2.5 KM curves with time-varying discordance

## Ignoring unknown labels:
## • colour : "Strata"

## Ignoring unknown labels:
## • colour : "Strata"


2.6 Time-varying Cox models with labs captured at the moment discordance is defined

Here we:

  • Define an index time per patient:
    • first_discord_time if they ever become discordant,
    • otherwise time_on.
  • Grab the nearest lab row in model_fit_complications to that index time (you can cap at 24 hours if you want).
  • Merge those covariates into the time-varying datasets and fit Cox models.
Time difference (hours) between index time and matched lab per patient
n_patients_with_covars median_time_diff_hours max_time_diff_hours
113 26.12 332.18
Thrombosis TV data: intervals by discordance group (with indexed labs)
discord_group n
concordant 89
aPTT > antiXa 14
aPTT < antiXa 17
Bleeding TV data: intervals by discordance group (with indexed labs)
discord_group n
concordant 89
aPTT > antiXa 14
aPTT < antiXa 17
Time-varying Cox model (thrombosis): discordance + labs at time of first discordance
term std.error robust.se statistic p.value conf.low conf.high HR
discord_groupaPTT > antiXa 0.607 0.509 0.901 0.368 0.584 4.285 1.581
discord_groupaPTT < antiXa 0.627 0.648 0.608 0.543 0.417 5.276 1.483
international_normalization_ratio 0.780 0.851 0.647 0.518 0.327 9.195 1.734
nearest_bilirubin 0.194 0.220 -1.267 0.205 0.492 1.164 0.757
nearest_platelet 0.004 0.005 -0.045 0.964 0.990 1.009 1.000
heparin_infusion_dose_value_units_kg_hr 0.060 0.056 -1.651 0.099 0.817 1.017 0.912
weight 0.009 0.008 0.596 0.551 0.989 1.021 1.005
Time-varying Cox model (bleeding): discordance + labs at time of first discordance
term std.error robust.se statistic p.value conf.low conf.high HR
discord_groupaPTT > antiXa 1.454 1.601 2.103 0.036 1.257 669.228 28.999
discord_groupaPTT < antiXa 1.606 1.403 1.194 0.232 0.342 83.488 5.341
international_normalization_ratio 1.606 1.251 0.369 0.712 0.137 18.425 1.587
nearest_bilirubin 0.307 0.230 0.987 0.324 0.799 1.970 1.255
nearest_platelet 0.011 0.011 0.859 0.390 0.988 1.031 1.009
heparin_infusion_dose_value_units_kg_hr 0.130 0.094 -0.586 0.558 0.787 1.138 0.946
weight 0.024 0.024 0.150 0.881 0.958 1.051 1.004

Comments on discrepancy between logistic and survival analyses

  • Logistic regression treats discordance as fixed (ever vs never) or at first discordance. Cox regression treats it as time-varying, so:

  • If a patient is discordant late, their earlier follow-up counts as “non-exposed” in Cox.

  • Logistic regression collapses all follow-up into a single binary exposure.

  • Even with post-discordance events only, this leads to different denominators and risk attribution.

We are likely very underpowered given infrequent events and small discordant subgroups (n = 11 and n = 17) and a time-varying exposure.

  • Ultimately this is exploratory in nature.

4. Tertiary outcomes, i.e. those which may not be solely thrombotic or hemorrhagic, but might be associated with discordance - for publication

Note: composited renal failure types into renal_failure_any

Ultimately there are very few of these outcomes (except renal failure and death).

5. Do counts of discordance differ when using classical (range-based) discordance categorization versus those identified with polynomial model? - CONSIDER FOR ADDITIONAL ABSTRACT

Note that this analysis eliminated 1 lab results in which aPTT was above typical goal rangs and time-matched anti-Xa was below typical goal range and 1 lab result in which aPTT was below typical goal range and time-matched anti-Xa was above typical goal range.

## # A tibble: 5 × 2
## # Groups:   concordance_classic_simple [5]
##   concordance_classic_simple       n
##   <fct>                        <int>
## 1 concordant                     379
## 2 discordant aPTT below antiXa   148
## 3 discordant aPTT above antiXa    42
## 4 high aPTT low antiXa             1
## 5 low aPTT high antiXa             1
## # A tibble: 5 × 2
## # Groups:   concordance_low_simple [5]
##   concordance_low_simple           n
##   <fct>                        <int>
## 1 concordant                     327
## 2 discordant aPTT below antiXa   183
## 3 discordant aPTT above antiXa    59
## 4 high aPTT low antiXa             1
## 5 low aPTT high antiXa             1
## 
## Counts (Classic):
## # A tibble: 2 × 2
##   classic_discordant     n
##   <lgl>              <int>
## 1 FALSE                 49
## 2 TRUE                  63
## 
## Counts (Modeled):
## # A tibble: 2 × 2
##   modeled_discordant     n
##   <lgl>              <int>
## 1 FALSE                 77
## 2 TRUE                  35
## 
## Classic vs Modeled Discordance Table:
##        modeled
## classic FALSE TRUE
##   FALSE    43    6
##   TRUE     34   29
## Warning in tidy.table(.): 'tidy.table' is deprecated.
## Use 'tibble::as_tibble()' instead.
## See help("Deprecated")
## # A tibble: 4 × 3
##   classic modeled     n
##   <chr>   <chr>   <int>
## 1 FALSE   FALSE      43
## 2 TRUE    FALSE      34
## 3 FALSE   TRUE        6
## 4 TRUE    TRUE       29
## 
## McNemar Test:
## 
##  McNemar's Chi-squared test with continuity correction
## 
## data:  discord_table
## McNemar's chi-squared = 18.225, df = 1, p-value = 1.963e-05
## # A tibble: 1 × 4
##   statistic   p.value parameter method                                          
##       <dbl>     <dbl>     <dbl> <chr>                                           
## 1      18.2 0.0000196         1 McNemar's Chi-squared test with continuity corr…
## === 3×3 Classification Table (Classic vs Polynomial Model) ===
##                modeled
## classic         aPTT < antiXa aPTT > antiXa concordant
##   aPTT < antiXa            14             4         30
##   aPTT > antiXa             0            11          4
##   concordant                4             2         43
## 
## === Chi-square Test ===
## 
##  Pearson's Chi-squared test with simulated p-value (based on 5000
##  replicates)
## 
## data:  discord_table_full
## X-squared = 55.029, df = NA, p-value = 2e-04
## 
## === Discordant-Only 2×2 Table (Low vs High) ===
##                modeled
## classic         aPTT < antiXa aPTT > antiXa concordant
##   aPTT < antiXa            14             4         30
##   aPTT > antiXa             0            11          4
##   concordant                4             2          0
## Warning in tidy.table(.): 'tidy.table' is deprecated.
## Use 'tibble::as_tibble()' instead.
## See help("Deprecated")
## # A tibble: 9 × 3
##   classic       modeled           n
##   <chr>         <chr>         <int>
## 1 aPTT < antiXa aPTT < antiXa    14
## 2 aPTT > antiXa aPTT < antiXa     0
## 3 concordant    aPTT < antiXa     4
## 4 aPTT < antiXa aPTT > antiXa     4
## 5 aPTT > antiXa aPTT > antiXa    11
## 6 concordant    aPTT > antiXa     2
## 7 aPTT < antiXa concordant       30
## 8 aPTT > antiXa concordant        4
## 9 concordant    concordant        0
## 
## === Chi-square Test (Discordant Types Only) ===
## 
##  Pearson's Chi-squared test with simulated p-value (based on 5000
##  replicates)
## 
## data:  discord_types
## X-squared = 33.891, df = NA, p-value = 2e-04
## # A tibble: 1 × 4
##   statistic  p.value parameter method                                           
##       <dbl>    <dbl> <lgl>     <chr>                                            
## 1      33.9 0.000200 NA        "Pearson's Chi-squared test with simulated p-val…

6. Do counts of complications by discordance type differ when using classical (range-based) discordance categorization versus those identified with polynomial model?

Note that this analysis eliminated 1 lab results in which aPTT was above typical goal range and time-matched anti-Xa was below typical goal range and 1 lab result in which aPTT was below typical goal range and time-matched anti-Xa was above typical goal range.

## 
## =============================
## Category: aPTT < antiXa 
## =============================
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    48       20       0.417
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    18        4       0.222
## 
## 2×2 Thrombosis Table:
##         thrombosis no_thrombosis
## classic         20            28
## modeled          4            14
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 0.1649
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##   0.6438088 11.8457795
## sample estimates:
## odds ratio 
##   2.467387 
## 
## 
## 
## 
## =============================
## Category: aPTT > antiXa 
## =============================
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    15        6         0.4
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    17        6       0.353
## 
## 2×2 Thrombosis Table:
##         thrombosis no_thrombosis
## classic          6             9
## modeled          6            11
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 1
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.2311049 6.4469852
## sample estimates:
## odds ratio 
##   1.214552 
## 
## 
## 
## 
## =============================
## Category: concordant 
## =============================
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    49       18       0.367
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    77       34       0.442
## 
## 2×2 Thrombosis Table:
##         thrombosis no_thrombosis
## classic         18            31
## modeled         34            43
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 0.4607
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.3280859 1.6249909
## sample estimates:
## odds ratio 
##  0.7361483
## 
## =============================
## Category: aPTT < antiXa 
## =============================
## # A tibble: 1 × 3
##       n hemorrhage_n hemorrhage_rate
##   <int>        <int>           <dbl>
## 1    48            2          0.0417
## # A tibble: 1 × 3
##       n hemorrhage_n hemorrhage_rate
##   <int>        <int>           <dbl>
## 1    18            1          0.0556
## 
## 2×2 Hemorrhage Table:
##         hemorrhage no_hemorrhage
## classic          2            46
## modeled          1            17
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 1
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##   0.03641973 46.14255757
## sample estimates:
## odds ratio 
##    0.74273 
## 
## 
## 
## 
## =============================
## Category: aPTT > antiXa 
## =============================
## # A tibble: 1 × 3
##       n hemorrhage_n hemorrhage_rate
##   <int>        <int>           <dbl>
## 1    15            3             0.2
## # A tibble: 1 × 3
##       n hemorrhage_n hemorrhage_rate
##   <int>        <int>           <dbl>
## 1    17            4           0.235
## 
## 2×2 Hemorrhage Table:
##         hemorrhage no_hemorrhage
## classic          3            12
## modeled          4            13
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 1
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.09859548 5.98490546
## sample estimates:
## odds ratio 
##   0.817771 
## 
## 
## 
## 
## =============================
## Category: concordant 
## =============================
## # A tibble: 1 × 3
##       n hemorrhage_n hemorrhage_rate
##   <int>        <int>           <dbl>
## 1    49            3          0.0612
## # A tibble: 1 × 3
##       n hemorrhage_n hemorrhage_rate
##   <int>        <int>           <dbl>
## 1    77            3          0.0390
## 
## 2×2 Hemorrhage Table:
##         hemorrhage no_hemorrhage
## classic          3            46
## modeled          3            74
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 0.6769
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##   0.2058079 12.4748253
## sample estimates:
## odds ratio 
##   1.602364
## 
## =============================
## Low Range vs Polynomial — Thrombosis
## Category: aPTT < antiXa 
## =============================
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    65       24       0.369
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    18        4       0.222
## 
## 2×2 Table:
##           thrombosis no_thrombosis
## low_range         24            41
## modeled            4            14
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 0.2766
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.5519251 9.4577870
## sample estimates:
## odds ratio 
##   2.032359 
## 
## 
## 
## 
## =============================
## Low Range vs Polynomial — Thrombosis
## Category: aPTT > antiXa 
## =============================
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    19        8       0.421
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    17        6       0.353
## 
## 2×2 Table:
##           thrombosis no_thrombosis
## low_range          8            11
## modeled            6            11
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 0.7419
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.2855128 6.3885568
## sample estimates:
## odds ratio 
##   1.322697 
## 
## 
## 
## 
## =============================
## Low Range vs Polynomial — Thrombosis
## Category: concordant 
## =============================
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    28       12       0.429
## # A tibble: 1 × 3
##       n thromb_n thromb_rate
##   <int>    <int>       <dbl>
## 1    77       34       0.442
## 
## 2×2 Table:
##           thrombosis no_thrombosis
## low_range         12            16
## modeled           34            43
## 
## Fisher Test:
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table_mat
## p-value = 1
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.3573489 2.4714823
## sample estimates:
## odds ratio 
##  0.9489871

LAB based unadjusted analysis => NOT TO REPORT

## # A tibble: 3 × 4
##   unusual_type      n hemorrhage_rate thrombosis_rate
##   <fct>         <int>           <dbl>           <dbl>
## 1 concordant      477            7.13            29.8
## 2 aPTT > antiXa    36           11.1             25  
## 3 aPTT < antiXa    58            1.72            24.1
## 
## Call:  glm(formula = hemorrhage_any ~ unusual_type, family = binomial, 
##     data = model_fit_complications)
## 
## Coefficients:
##               (Intercept)  unusual_typeaPTT > antiXa  
##                   -2.5672                     0.4878  
## unusual_typeaPTT < antiXa  
##                   -1.4758  
## 
## Degrees of Freedom: 570 Total (i.e. Null);  568 Residual
## Null Deviance:       284.6 
## Residual Deviance: 280.3     AIC: 286.3
## 
## Call:
## glm(formula = hemorrhage_any ~ unusual_type, family = binomial, 
##     data = model_fit_complications)
## 
## Coefficients:
##                           Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                -2.5672     0.1780 -14.426   <2e-16 ***
## unusual_typeaPTT > antiXa   0.4878     0.5594   0.872    0.383    
## unusual_typeaPTT < antiXa  -1.4758     1.0241  -1.441    0.150    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 284.61  on 570  degrees of freedom
## Residual deviance: 280.33  on 568  degrees of freedom
## AIC: 286.33
## 
## Number of Fisher Scoring iterations: 6
## 
## Call:  glm(formula = thrombosis_any ~ unusual_type, family = binomial, 
##     data = model_fit_complications)
## 
## Coefficients:
##               (Intercept)  unusual_typeaPTT > antiXa  
##                   -0.8583                    -0.2403  
## unusual_typeaPTT < antiXa  
##                   -0.2868  
## 
## Degrees of Freedom: 570 Total (i.e. Null);  568 Residual
## Null Deviance:       686.6 
## Residual Deviance: 685.5     AIC: 691.5
## 
## Call:
## glm(formula = thrombosis_any ~ unusual_type, family = binomial, 
##     data = model_fit_complications)
## 
## Coefficients:
##                           Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                -0.8583     0.1001  -8.571   <2e-16 ***
## unusual_typeaPTT > antiXa  -0.2403     0.3977  -0.604    0.546    
## unusual_typeaPTT < antiXa  -0.2868     0.3228  -0.889    0.374    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 686.60  on 570  degrees of freedom
## Residual deviance: 685.49  on 568  degrees of freedom
## AIC: 691.49
## 
## Number of Fisher Scoring iterations: 4

LAB based adjusted analysis - note that this NOT PATIENT LEVEL => NOT TO REPORT

## 
## Call:
## glm(formula = hemorrhage_any ~ unusual_type + duration_to_lab + 
##     international_normalization_ratio + fibrinogen + nearest_bilirubin + 
##     weight + heparin_infusion_dose_value_units_kg_hr, family = binomial, 
##     data = model_fit_complications)
## 
## Coefficients:
##                                           Estimate Std. Error z value Pr(>|z|)
## (Intercept)                              5.437e-01  3.189e+00   0.170  0.86462
## unusual_typeaPTT > antiXa               -1.629e+01  1.751e+03  -0.009  0.99258
## unusual_typeaPTT < antiXa               -4.178e-01  1.301e+00  -0.321  0.74816
## duration_to_lab                         -1.206e-03  4.098e-03  -0.294  0.76857
## international_normalization_ratio        1.358e+00  2.296e+00   0.592  0.55404
## fibrinogen                               2.194e-05  1.954e-03   0.011  0.99104
## nearest_bilirubin                       -4.498e-01  4.408e-01  -1.020  0.30753
## weight                                  -6.816e-02  2.174e-02  -3.135  0.00172
## heparin_infusion_dose_value_units_kg_hr  1.732e-01  9.296e-02   1.863  0.06248
##                                           
## (Intercept)                               
## unusual_typeaPTT > antiXa                 
## unusual_typeaPTT < antiXa                 
## duration_to_lab                           
## international_normalization_ratio         
## fibrinogen                                
## nearest_bilirubin                         
## weight                                  **
## heparin_infusion_dose_value_units_kg_hr . 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 86.459  on 167  degrees of freedom
## Residual deviance: 61.610  on 159  degrees of freedom
##   (403 observations deleted due to missingness)
## AIC: 79.61
## 
## Number of Fisher Scoring iterations: 16
VIF collinearity check for hemorrhage multivariable model
GVIF Df GVIF^(1/(2*Df))
unusual_type 1.355896 2 1.079087
duration_to_lab 1.755864 1 1.325090
international_normalization_ratio 1.304064 1 1.141956
fibrinogen 1.407007 1 1.186173
nearest_bilirubin 1.147931 1 1.071416
weight 1.595967 1 1.263316
heparin_infusion_dose_value_units_kg_hr 1.836584 1 1.355206
## # A tibble: 9 × 8
##   term                        OR conf.low conf.high   p_raw  p_fdr p_holm p_bonf
##   <chr>                    <dbl>    <dbl>     <dbl>   <dbl>  <dbl>  <dbl>  <dbl>
## 1 (Intercept)            1.72e+0  0.00588  2.22e+ 3 0.865   0.993  1      1     
## 2 unusual_typeaPTT > an… 8.44e-8 NA        7.69e+56 0.993   0.993  1      1     
## 3 unusual_typeaPTT < an… 6.59e-1  0.0276   7.14e+ 0 0.748   0.993  1      1     
## 4 duration_to_lab        9.99e-1  0.990    1.01e+ 0 0.769   0.993  1      1     
## 5 international_normali… 3.89e+0  0.0134   1.70e+ 2 0.554   0.993  1      1     
## 6 fibrinogen             1.00e+0  0.996    1.00e+ 0 0.991   0.993  1      1     
## 7 nearest_bilirubin      6.38e-1  0.209    1.21e+ 0 0.308   0.923  1      1     
## 8 weight                 9.34e-1  0.890    9.71e- 1 0.00172 0.0155 0.0155 0.0155
## 9 heparin_infusion_dose… 1.19e+0  1.00     1.45e+ 0 0.0625  0.281  0.500  0.562
## [1] TRUE
##                
##                 FALSE TRUE
##   concordant      443   34
##   aPTT > antiXa    32    4
##   aPTT < antiXa    57    1

Hemorrhage Firth Penalized Regression Results
term estimate OR conf.low conf.high p_raw p_fdr p_holm p_bonf
(Intercept) -0.4517335 0.6365238 0.0055107 394.8943525 0.8573556 0.9645251 1.0000000 1.0000000
unusual_typeaPTT > antiXa -1.1943994 0.3028858 0.0019908 4.7298196 0.4328422 0.8319527 1.0000000 1.0000000
unusual_typeaPTT < antiXa -0.2020069 0.8170893 0.0680678 6.1958257 0.8512867 0.9645251 1.0000000 1.0000000
duration_to_lab -0.0008927 0.9991077 0.9914045 1.0066575 0.8082157 0.9645251 1.0000000 1.0000000
international_normalization_ratio 1.7131475 5.5463913 0.0361873 90.6128738 0.3617986 0.8319527 1.0000000 1.0000000
fibrinogen -0.0000540 0.9999460 0.9962827 1.0036019 0.9762417 0.9762417 1.0000000 1.0000000
nearest_bilirubin -0.2232760 0.7998941 0.3003558 1.2897960 0.4621959 0.8319527 1.0000000 1.0000000
weight -0.0575024 0.9441196 0.9050462 0.9775113 0.0009199 0.0082792 0.0082792 0.0082792
heparin_infusion_dose_value_units_kg_hr 0.1432434 1.1540107 0.9887063 1.3823250 0.0701087 0.3154892 0.5608697 0.6309784
## 
## Call:
## glm(formula = thrombosis_any ~ unusual_type + international_normalization_ratio + 
##     heparin_infusion_dose_value_units_kg_hr + duration_to_lab + 
##     fibrinogen + nearest_bilirubin + weight, family = binomial, 
##     data = model_fit_complications)
## 
## Coefficients:
##                                           Estimate Std. Error z value Pr(>|z|)
## (Intercept)                              4.201e-01  1.858e+00   0.226 0.821126
## unusual_typeaPTT > antiXa               -1.488e+01  1.056e+03  -0.014 0.988756
## unusual_typeaPTT < antiXa                1.348e+00  5.398e-01   2.497 0.012509
## international_normalization_ratio       -5.654e-01  1.228e+00  -0.460 0.645206
## heparin_infusion_dose_value_units_kg_hr -2.186e-01  6.284e-02  -3.478 0.000505
## duration_to_lab                         -7.959e-03  3.629e-03  -2.193 0.028276
## fibrinogen                              -8.438e-04  9.307e-04  -0.907 0.364581
## nearest_bilirubin                        2.562e-02  1.347e-01   0.190 0.849085
## weight                                   2.474e-02  1.010e-02   2.449 0.014327
##                                            
## (Intercept)                                
## unusual_typeaPTT > antiXa                  
## unusual_typeaPTT < antiXa               *  
## international_normalization_ratio          
## heparin_infusion_dose_value_units_kg_hr ***
## duration_to_lab                         *  
## fibrinogen                                 
## nearest_bilirubin                          
## weight                                  *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 202.82  on 167  degrees of freedom
## Residual deviance: 162.36  on 159  degrees of freedom
##   (403 observations deleted due to missingness)
## AIC: 180.36
## 
## Number of Fisher Scoring iterations: 15
## # A tibble: 9 × 7
##   term                   estimate std.error statistic p.value conf.low conf.high
##   <chr>                     <dbl>     <dbl>     <dbl>   <dbl>    <dbl>     <dbl>
## 1 (Intercept)             1.52e+0   1.86e+0    0.226  8.21e-1   0.0413  7.45e+ 1
## 2 unusual_typeaPTT > an…  3.44e-7   1.06e+3   -0.0141 9.89e-1  NA       3.54e+40
## 3 unusual_typeaPTT < an…  3.85e+0   5.40e-1    2.50   1.25e-2   1.37    1.16e+ 1
## 4 international_normali…  5.68e-1   1.23e+0   -0.460  6.45e-1   0.0384  6.00e+ 0
## 5 heparin_infusion_dose…  8.04e-1   6.28e-2   -3.48   5.05e-4   0.705   9.03e- 1
## 6 duration_to_lab         9.92e-1   3.63e-3   -2.19   2.83e-2   0.985   9.99e- 1
## 7 fibrinogen              9.99e-1   9.31e-4   -0.907  3.65e-1   0.997   1.00e+ 0
## 8 nearest_bilirubin       1.03e+0   1.35e-1    0.190  8.49e-1   0.769   1.32e+ 0
## 9 weight                  1.03e+0   1.01e-2    2.45   1.43e-2   1.01    1.05e+ 0
VIF collinearity check for thrombosis multivariable model
GVIF Df GVIF^(1/(2*Df))
unusual_type 1.258849 2 1.059238
international_normalization_ratio 1.408611 1 1.186849
heparin_infusion_dose_value_units_kg_hr 1.503484 1 1.226166
duration_to_lab 1.323139 1 1.150278
fibrinogen 1.322245 1 1.149889
nearest_bilirubin 1.418127 1 1.190851
weight 1.346531 1 1.160401
## # A tibble: 9 × 8
##   term                     OR conf.low conf.high   p_raw   p_fdr  p_holm  p_bonf
##   <chr>                 <dbl>    <dbl>     <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
## 1 (Intercept)         1.52e+0   0.0413  7.45e+ 1 8.21e-1 0.955   1       1      
## 2 unusual_typeaPTT >… 3.44e-7  NA       3.54e+40 9.89e-1 0.989   1       1      
## 3 unusual_typeaPTT <… 3.85e+0   1.37    1.16e+ 1 1.25e-2 0.0430  0.100   0.113  
## 4 international_norm… 5.68e-1   0.0384  6.00e+ 0 6.45e-1 0.955   1       1      
## 5 heparin_infusion_d… 8.04e-1   0.705   9.03e- 1 5.05e-4 0.00454 0.00454 0.00454
## 6 duration_to_lab     9.92e-1   0.985   9.99e- 1 2.83e-2 0.0636  0.170   0.254  
## 7 fibrinogen          9.99e-1   0.997   1.00e+ 0 3.65e-1 0.656   1       1      
## 8 nearest_bilirubin   1.03e+0   0.769   1.32e+ 0 8.49e-1 0.955   1       1      
## 9 weight              1.03e+0   1.01    1.05e+ 0 1.43e-2 0.0430  0.100   0.129
## [1] TRUE
##                
##                 FALSE TRUE
##   concordant      335  142
##   aPTT > antiXa    27    9
##   aPTT < antiXa    44   14

Thrombosis Firth Penalized Regression Results
term estimate OR conf.low conf.high p_raw p_fdr p_holm p_bonf
(Intercept) 0.3112238 1.3650946 0.0489856 50.5729181 0.8542002 0.8542002 1.0000000 1.0000000
unusual_typeaPTT > antiXa -0.8812509 0.4142644 0.0029282 5.0395611 0.5416406 0.8124609 1.0000000 1.0000000
unusual_typeaPTT < antiXa 1.2449190 3.4726536 1.2893237 9.9483446 0.0136282 0.0408845 0.0953973 0.1226536
duration_to_lab -0.0073757 0.9926514 0.9854777 0.9991030 0.0247555 0.0556998 0.1485328 0.2227992
international_normalization_ratio -0.4233769 0.6548318 0.0549153 5.3981260 0.6915597 0.8542002 1.0000000 1.0000000
fibrinogen -0.0008607 0.9991397 0.9973761 1.0009172 0.3391874 0.6105373 1.0000000 1.0000000
nearest_bilirubin 0.0386472 1.0394037 0.7886354 1.3062943 0.7627375 0.8542002 1.0000000 1.0000000
weight 0.0223096 1.0225603 1.0054031 1.0444797 0.0081549 0.0366972 0.0652394 0.0733944
heparin_infusion_dose_value_units_kg_hr -0.1996967 0.8189791 0.7221164 0.9152349 0.0002459 0.0022128 0.0022128 0.0022128

LAB based, not patient-level, Sensitivity Analysis in which Discordance is Grouped - not to report

hemorrhage_simple = glm(hemorrhage_any ~ discordance_any + duration_to_lab + nearest_bilirubin + fibrinogen + international_normalization_ratio + weight + heparin_infusion_dose_value_units_kg_hr, data = model_fit_complications, family = binomial)

hemorrhage_simple %>% broom::tidy(exponentiate = TRUE, conf.int = TRUE)
## # A tibble: 8 × 7
##   term                   estimate std.error statistic p.value conf.low conf.high
##   <chr>                     <dbl>     <dbl>     <dbl>   <dbl>    <dbl>     <dbl>
## 1 (Intercept)               1.44    3.15        0.116 0.908    0.00507  1826.   
## 2 discordance_anydiscor…    0.351   1.25       -0.836 0.403    0.0154      3.27 
## 3 duration_to_lab           1.000   0.00402    -0.102 0.919    0.991       1.01 
## 4 nearest_bilirubin         0.635   0.451      -1.01  0.314    0.204       1.21 
## 5 fibrinogen                1.000   0.00191    -0.152 0.879    0.996       1.00 
## 6 international_normali…    4.12    2.25        0.629 0.529    0.0138    173.   
## 7 weight                    0.938   0.0209     -3.07  0.00218  0.896       0.974
## 8 heparin_infusion_dose…    1.17    0.0900      1.74  0.0818   0.989       1.41
thrombosis_simple = glm(thrombosis_any ~ discordance_any + duration_to_lab + international_normalization_ratio + weight + heparin_infusion_dose_value_units_kg_hr + nearest_bilirubin + fibrinogen, data = model_fit_complications, family = binomial)

thrombosis_simple %>% broom::tidy(exponentiate = TRUE, conf.int = TRUE)
## # A tibble: 8 × 7
##   term                   estimate std.error statistic p.value conf.low conf.high
##   <chr>                     <dbl>     <dbl>     <dbl>   <dbl>    <dbl>     <dbl>
## 1 (Intercept)               0.994  1.86      -0.00297 9.98e-1   0.0268    48.6  
## 2 discordance_anydiscor…    2.96   0.513      2.12    3.42e-2   1.10       8.34 
## 3 duration_to_lab           0.993  0.00349   -1.90    5.77e-2   0.986      1.000
## 4 international_normali…    0.591  1.23      -0.428   6.69e-1   0.0397     6.26 
## 5 weight                    1.03   0.0103     2.87    4.17e-3   1.01       1.05 
## 6 heparin_infusion_dose…    0.787  0.0629    -3.82    1.36e-4   0.690      0.884
## 7 nearest_bilirubin         1.05   0.133      0.367   7.13e-1   0.791      1.34 
## 8 fibrinogen                0.999  0.000927  -1.04    2.98e-1   0.997      1.00

Lab-based, not patient level, Sensitivity Analysis in which outcomes are grouped

complication_simple = glm(coag_event_any ~ unusual_type + duration_to_lab + nearest_bilirubin + fibrinogen + international_normalization_ratio + weight + heparin_infusion_dose_value_units_kg_hr, data = model_fit_complications, family = binomial)

complication_simple %>% broom::tidy()
## # A tibble: 8 × 5
##   term                                     estimate std.error statistic p.value
##   <chr>                                       <dbl>     <dbl>     <dbl>   <dbl>
## 1 (Intercept)                             -2.66e+ 1   545666. -4.87e- 5   1.000
## 2 unusual_typeaPTT < antiXa               -5.55e-16   124884. -4.44e-21   1    
## 3 duration_to_lab                          1.77e-17      625.  2.83e-20   1    
## 4 nearest_bilirubin                        1.22e-15    50094.  2.44e-20   1    
## 5 fibrinogen                               2.92e-18      298.  9.80e-21   1    
## 6 international_normalization_ratio       -1.93e-14   349714. -5.52e-20   1    
## 7 weight                                  -1.15e-16     2719. -4.23e-20   1    
## 8 heparin_infusion_dose_value_units_kg_hr  1.08e-15    11855.  9.12e-20   1

Standard logistic regression had high separation based on discordance type, likely due to uncommon outcome among a relatively small sample size with several critical covariables. Thus, Firth penalized logistic regression used to compute odds ratios and p-values.

CONCLUSIONS